]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Port PopupMenu to new Lang.Class framework
authorGiovanni Campagna <gcampagna@src.gnome.org>
Sun, 20 Nov 2011 13:10:48 +0000 (14:10 +0100)
committerGiovanni Campagna <gcampagna@src.gnome.org>
Thu, 24 Nov 2011 08:50:04 +0000 (09:50 +0100)
The Lang module in gjs has recently gained a small yet powerful
Class framework, that should help improve the readability of code
when using complex inheritance.
This commit starts porting shell code, by rewriting all classes in
popupMenu.js (and all derived classes) to Lang.Class.

https://bugzilla.gnome.org/show_bug.cgi?id=664436

js/ui/appDisplay.js
js/ui/popupMenu.js
js/ui/shellEntry.js
js/ui/status/keyboard.js
js/ui/status/network.js
js/ui/status/power.js
js/ui/userMenu.js

index ec86c37db99a8350ab3988c38ab3533dd811c507..98f16e8b7c49585576c799b3d16bc9ab49d16ce4 100644 (file)
@@ -623,19 +623,16 @@ AppWellIcon.prototype = {
 };
 Signals.addSignalMethods(AppWellIcon.prototype);
 
-function AppIconMenu(source) {
-    this._init(source);
-}
-
-AppIconMenu.prototype = {
-    __proto__: PopupMenu.PopupMenu.prototype,
+const AppIconMenu = new Lang.Class({
+    Name: 'AppIconMenu',
+    Extends: PopupMenu.PopupMenu,
 
     _init: function(source) {
         let side = St.Side.LEFT;
         if (St.Widget.get_default_direction() == St.TextDirection.RTL)
             side = St.Side.RIGHT;
 
-        PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side);
+        this.parent(source.actor, 0.5, side);
 
         // We want to keep the item hovered while the menu is up
         this.blockSourceEvents = true;
@@ -723,5 +720,5 @@ AppIconMenu.prototype = {
         }
         this.close();
     }
-};
+});
 Signals.addSignalMethods(AppIconMenu.prototype);
index 6aee9f4191de743c276d3b3870b094a61e057198..a8d3384f6cd7bf2689d5384f33410c44d25d407a 100644 (file)
@@ -26,11 +26,9 @@ function _ensureStyle(actor) {
         actor.ensure_style();
 }
 
-function PopupBaseMenuItem(params) {
-    this._init(params);
-}
+const PopupBaseMenuItem = new Lang.Class({
+    Name: 'PopupBaseMenuItem',
 
-PopupBaseMenuItem.prototype = {
     _init: function (params) {
         params = Params.parse (params, { reactive: true,
                                          activate: true,
@@ -377,33 +375,27 @@ PopupBaseMenuItem.prototype = {
                 x -= availWidth + this._spacing;
         }
     }
-};
+});
 Signals.addSignalMethods(PopupBaseMenuItem.prototype);
 
-function PopupMenuItem() {
-    this._init.apply(this, arguments);
-}
-
-PopupMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupMenuItem = new Lang.Class({
+    Name: 'PopupMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function (text, params) {
-        PopupBaseMenuItem.prototype._init.call(this, params);
+        this.parent(params);
 
         this.label = new St.Label({ text: text });
         this.addActor(this.label);
     }
-};
-
-function PopupSeparatorMenuItem() {
-    this._init();
-}
+});
 
-PopupSeparatorMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupSeparatorMenuItem = new Lang.Class({
+    Name: 'PopupSeparatorMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function () {
-        PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
+        this.parent({ reactive: false });
 
         this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
         this.addActor(this._drawingArea, { span: -1, expand: true });
@@ -429,22 +421,19 @@ PopupSeparatorMenuItem.prototype = {
         cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
         cr.fill();
     }
-};
+});
 
 const PopupAlternatingMenuItemState = {
     DEFAULT: 0,
     ALTERNATIVE: 1
 }
 
-function PopupAlternatingMenuItem() {
-    this._init.apply(this, arguments);
-}
-
-PopupAlternatingMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupAlternatingMenuItem = new Lang.Class({
+    Name: 'PopupAlternatingMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function(text, alternateText, params) {
-        PopupBaseMenuItem.prototype._init.call(this, params);
+        this.parent(params);
         this.actor.add_style_class_name('popup-alternating-menu-item');
 
         this._text = text;
@@ -530,17 +519,14 @@ PopupAlternatingMenuItem.prototype = {
 
         this._updateLabel();
     }
-};
-
-function PopupSliderMenuItem() {
-    this._init.apply(this, arguments);
-}
+});
 
-PopupSliderMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupSliderMenuItem = new Lang.Class({
+    Name: 'PopupSliderMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function(value) {
-        PopupBaseMenuItem.prototype._init.call(this, { activate: false });
+        this.parent({ activate: false });
 
         this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
 
@@ -716,13 +702,11 @@ PopupSliderMenuItem.prototype = {
         }
         return false;
     }
-};
+});
 
-function Switch() {
-    this._init.apply(this, arguments);
-}
+const Switch = new Lang.Class({
+    Name: 'Switch',
 
-Switch.prototype = {
     _init: function(state) {
         this.actor = new St.Bin({ style_class: 'toggle-switch' });
         // Translators: this MUST be either "toggle-switch-us"
@@ -745,17 +729,14 @@ Switch.prototype = {
     toggle: function() {
         this.setToggleState(!this.state);
     }
-};
-
-function PopupSwitchMenuItem() {
-    this._init.apply(this, arguments);
-}
+});
 
-PopupSwitchMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupSwitchMenuItem = new Lang.Class({
+    Name: 'PopupSwitchMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function(text, active, params) {
-        PopupBaseMenuItem.prototype._init.call(this, params);
+        this.parent(params);
 
         this.label = new St.Label({ text: text });
         this._switch = new Switch(active);
@@ -805,17 +786,14 @@ PopupSwitchMenuItem.prototype = {
     setToggleState: function(state) {
         this._switch.setToggleState(state);
     }
-};
+});
 
-function PopupImageMenuItem() {
-    this._init.apply(this, arguments);
-}
-
-PopupImageMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupImageMenuItem = new Lang.Class({
+    Name: 'PopupImageMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function (text, iconName, params) {
-        PopupBaseMenuItem.prototype._init.call(this, params);
+        this.parent(params);
 
         this.label = new St.Label({ text: text });
         this.addActor(this.label);
@@ -828,13 +806,12 @@ PopupImageMenuItem.prototype = {
     setIcon: function(name) {
         this._icon.icon_name = name;
     }
-};
+});
 
-function PopupMenuBase() {
-    throw new TypeError('Trying to instantiate abstract class PopupMenuBase');
-}
+const PopupMenuBase = new Lang.Class({
+    Name: 'PopupMenuBase',
+    Abstract: true,
 
-PopupMenuBase.prototype = {
     _init: function(sourceActor, styleClass) {
         this.sourceActor = sourceActor;
 
@@ -1139,18 +1116,15 @@ PopupMenuBase.prototype = {
 
         this.emit('destroy');
     }
-};
+});
 Signals.addSignalMethods(PopupMenuBase.prototype);
 
-function PopupMenu() {
-    this._init.apply(this, arguments);
-}
-
-PopupMenu.prototype = {
-    __proto__: PopupMenuBase.prototype,
+const PopupMenu = new Lang.Class({
+    Name: 'PopupMenu',
+    Extends: PopupMenuBase,
 
     _init: function(sourceActor, arrowAlignment, arrowSide) {
-        PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content');
+        this.parent(sourceActor, 'popup-menu-content');
 
         this._arrowAlignment = arrowAlignment;
         this._arrowSide = arrowSide;
@@ -1235,17 +1209,14 @@ PopupMenu.prototype = {
         this.isOpen = false;
         this.emit('open-state-changed', false);
     }
-};
-
-function PopupSubMenu() {
-    this._init.apply(this, arguments);
-}
+});
 
-PopupSubMenu.prototype = {
-    __proto__: PopupMenuBase.prototype,
+const PopupSubMenu = new Lang.Class({
+    Name: 'PopupSubMenu',
+    Extends: PopupMenuBase,
 
     _init: function(sourceActor, sourceArrow) {
-        PopupMenuBase.prototype._init.call(this, sourceActor);
+        this.parent(sourceActor);
 
         this._arrow = sourceArrow;
         this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER;
@@ -1400,7 +1371,7 @@ PopupSubMenu.prototype = {
 
         return false;
     }
-};
+});
 
 /**
  * PopupMenuSection:
@@ -1410,15 +1381,12 @@ PopupSubMenu.prototype = {
  * can add it to another menu), but is completely transparent
  * to the user
  */
-function PopupMenuSection() {
-    this._init.apply(this, arguments);
-}
-
-PopupMenuSection.prototype = {
-    __proto__: PopupMenuBase.prototype,
+const PopupMenuSection = new Lang.Class({
+    Name: 'PopupMenuSection',
+    Extends: PopupMenuBase,
 
     _init: function() {
-        PopupMenuBase.prototype._init.call(this);
+        this.parent();
 
         this.actor = this.box;
         this.actor._delegate = this;
@@ -1429,17 +1397,14 @@ PopupMenuSection.prototype = {
     // corresponding signal so children can still pick it up
     open: function(animate) { this.emit('open-state-changed', true); },
     close: function() { this.emit('open-state-changed', false); },
-}
-
-function PopupSubMenuMenuItem() {
-    this._init.apply(this, arguments);
-}
+});
 
-PopupSubMenuMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupSubMenuMenuItem = new Lang.Class({
+    Name: 'PopupSubMenuMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function(text) {
-        PopupBaseMenuItem.prototype._init.call(this);
+        this.parent();
 
         this.actor.add_style_class_name('popup-submenu-menu-item');
 
@@ -1461,7 +1426,8 @@ PopupSubMenuMenuItem.prototype = {
 
     destroy: function() {
         this.menu.destroy();
-        PopupBaseMenuItem.prototype.destroy.call(this);
+
+        this.parent();
     },
 
     _onKeyPressEvent: function(actor, event) {
@@ -1476,7 +1442,7 @@ PopupSubMenuMenuItem.prototype = {
             return true;
         }
 
-        return PopupBaseMenuItem.prototype._onKeyPressEvent.call(this, actor, event);
+        return this.parent(actor, event);
     },
 
     activate: function(event) {
@@ -1486,18 +1452,15 @@ PopupSubMenuMenuItem.prototype = {
     _onButtonReleaseEvent: function(actor) {
         this.menu.toggle();
     }
-};
-
-function PopupComboMenu() {
-    this._init.apply(this, arguments);
-}
+});
 
-PopupComboMenu.prototype = {
-    __proto__: PopupMenuBase.prototype,
+const PopupComboMenu = new Lang.Class({
+    Name: 'PopupComboMenu',
+    Extends: PopupMenuBase,
 
     _init: function(sourceActor) {
-        PopupMenuBase.prototype._init.call(this,
-                                           sourceActor, 'popup-combo-menu');
+        this.parent(sourceActor, 'popup-combo-menu');
+
         this.actor = this.box;
         this.actor._delegate = this;
         this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
@@ -1602,17 +1565,14 @@ PopupComboMenu.prototype = {
     getItemVisible: function(position) {
         return this._getMenuItems()[position].actor.visible;
     }
-};
+});
 
-function PopupComboBoxMenuItem() {
-    this._init.apply(this, arguments);
-}
-
-PopupComboBoxMenuItem.prototype = {
-    __proto__: PopupBaseMenuItem.prototype,
+const PopupComboBoxMenuItem = new Lang.Class({
+    Name: 'PopupComboBoxMenuItem',
+    Extends: PopupBaseMenuItem,
 
     _init: function (params) {
-        PopupBaseMenuItem.prototype._init.call(this, params);
+        this.parent(params);
 
         this._itemBox = new Shell.Stack();
         this.addActor(this._itemBox);
@@ -1730,16 +1690,14 @@ PopupComboBoxMenuItem.prototype = {
         this.setActiveItem(position);
         this.emit('active-item-changed', position);
     }
-};
+});
 
 /* Basic implementation of a menu manager.
  * Call addMenu to add menus
  */
-function PopupMenuManager(owner) {
-    this._init(owner);
-}
+const PopupMenuManager = new Lang.Class({
+    Name: 'PopupMenuManager',
 
-PopupMenuManager.prototype = {
     _init: function(owner) {
         this._owner = owner;
         this.grabbed = false;
@@ -2011,4 +1969,4 @@ PopupMenuManager.prototype = {
         if (this._activeMenu != null)
             this._activeMenu.close(true);
     }
-};
+});
index 1dc00887a5c612653113be6746a13ff4b1faccd9..e348a80b7ff7752c85e05923ea55fe4fd81b4f2c 100644 (file)
@@ -7,18 +7,14 @@ const Main = imports.ui.main;
 const Params = imports.misc.params;
 const PopupMenu = imports.ui.popupMenu;
 
-
-function _EntryMenu(entry, params) {
-    this._init(entry, params);
-};
-
-_EntryMenu.prototype = {
-    __proto__: PopupMenu.PopupMenu.prototype,
+const _EntryMenu = new Lang.Class({
+    Name: 'ShellEntryMenu',
+    Extends: PopupMenu.PopupMenu,
 
     _init: function(entry, params) {
         params = Params.parse (params, { isPassword: false });
 
-        PopupMenu.PopupMenu.prototype._init.call(this, entry, 0, St.Side.TOP);
+        this.parent(entry, 0, St.Side.TOP);
 
         this.actor.add_style_class_name('entry-context-menu');
 
@@ -60,7 +56,7 @@ _EntryMenu.prototype = {
         if (!this.actor.navigate_focus(null, direction, false))
             this.actor.grab_key_focus();
 
-        PopupMenu.PopupMenu.prototype.open.call(this);
+        this.parent();
     },
 
     _updateCopyItem: function() {
@@ -103,8 +99,7 @@ _EntryMenu.prototype = {
         let visible = !!(this._entry.clutter_text.password_char);
         this._entry.clutter_text.set_password_char(visible ? '' : '\u25cf');
     }
-};
-
+});
 
 function _setMenuAlignment(entry, stageX) {
     let [success, entryX, entryY] = entry.transform_stage_point(stageX, 0);
index 231f0c78ec7896002fbf30d84a33120eb98e822d..f6f2d456ea00fb659c7765372979feeca6199fd0 100644 (file)
@@ -14,15 +14,12 @@ const PopupMenu = imports.ui.popupMenu;
 const PanelMenu = imports.ui.panelMenu;
 const Util = imports.misc.util;
 
-function LayoutMenuItem() {
-    this._init.apply(this, arguments);
-}
-
-LayoutMenuItem.prototype = {
-    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+const LayoutMenuItem = new Lang.Class({
+    Name: 'LayoutMenuItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
     _init: function(config, id, indicator, long_name) {
-        PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
+        this.parent();
 
         this._config = config;
         this._id = id;
@@ -33,10 +30,11 @@ LayoutMenuItem.prototype = {
     },
 
     activate: function(event) {
-        PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
+        this.parent(event);
+
         this._config.lock_group(this._id);
     }
-};
+});
 
 function XKBIndicator() {
     this._init.call(this);
index 7265873b33098bf85ce3801b411e24e2acafd52e..57edc9c862b3ef77b61cea3775ae97ff2d7ea92e 100644 (file)
@@ -97,15 +97,12 @@ function ssidToLabel(ssid) {
     return label;
 }
 
-function NMNetworkMenuItem() {
-    this._init.apply(this, arguments);
-}
-
-NMNetworkMenuItem.prototype = {
-    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+const NMNetworkMenuItem = new Lang.Class({
+    Name: 'NMNetworkMenuItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
     _init: function(accessPoints, title, params) {
-        PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
+        this.parent(params);
 
         accessPoints = sortAccessPoints(accessPoints);
         this.bestAP = accessPoints[0];
@@ -184,21 +181,18 @@ NMNetworkMenuItem.prototype = {
             apObj.updateId = 0;
         }
 
-        PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this);
+        this.parent();
     }
-};
-
-function NMWiredSectionTitleMenuItem() {
-    this._init.apply(this, arguments);
-}
+});
 
-NMWiredSectionTitleMenuItem.prototype = {
-    __proto__: PopupMenu.PopupSwitchMenuItem.prototype,
+const NMWiredSectionTitleMenuItem = new Lang.Class({
+    Name: 'NMWiredSectionTitleMenuItem',
+    Extends: PopupMenu.PopupSwitchMenuItem,
 
     _init: function(label, params) {
         params = params || { };
         params.style_class = 'popup-subtitle-menu-item';
-        PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, label, false, params);
+        this.parent(label, false, params);
     },
 
     updateForDevice: function(device) {
@@ -211,7 +205,7 @@ NMWiredSectionTitleMenuItem.prototype = {
     },
 
     activate: function(event) {
-        PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
+        this.parent(event);
 
         if (!this._device) {
             log('Section title activated when there is more than one device, should be non reactive');
@@ -230,19 +224,16 @@ NMWiredSectionTitleMenuItem.prototype = {
         else
             this._device.deactivate();
     }
-};
-
-function NMWirelessSectionTitleMenuItem() {
-    this._init.apply(this, arguments);
-}
+});
 
-NMWirelessSectionTitleMenuItem.prototype = {
-    __proto__: PopupMenu.PopupSwitchMenuItem.prototype,
+const NMWirelessSectionTitleMenuItem = new Lang.Class({
+    Name: 'NMWirelessSectionTitleMenuItem',
+    Extends: PopupMenu.PopupSwitchMenuItem,
 
     _init: function(client, property, title, params) {
         params = params || { };
         params.style_class = 'popup-subtitle-menu-item';
-        PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, title, false, params);
+        this.parent(title, false, params);
 
         this._client = client;
         this._property = property + '_enabled';
@@ -268,7 +259,7 @@ NMWirelessSectionTitleMenuItem.prototype = {
     },
 
     activate: function(event) {
-        PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
+        this.parent(event);
 
         this._client[this._setEnabledFunc](this._switch.state);
     },
@@ -285,7 +276,7 @@ NMWirelessSectionTitleMenuItem.prototype = {
 
         this.emit('enabled-changed', enabled);
     }
-};
+});
 
 function NMDevice() {
     throw new TypeError('Instantanting abstract class NMDevice');
index fa77d552aa164801545ccab0528ed954b2a5176c..836b010894bfa059df7d2daf66f1bac709c830aa 100644 (file)
@@ -165,15 +165,12 @@ Indicator.prototype = {
     }
 };
 
-function DeviceItem() {
-    this._init.apply(this, arguments);
-}
-
-DeviceItem.prototype = {
-    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+const DeviceItem = new Lang.Class({
+    Name: 'DeviceItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
     _init: function(device) {
-        PopupMenu.PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
+        this.parent({ reactive: false });
 
         let [device_id, device_type, icon, percentage, state, time] = device;
 
@@ -220,4 +217,4 @@ DeviceItem.prototype = {
             return _("Unknown");
         }
     }
-}
+});
index 7e4fbe30c1150a9caf0fda42ba4d4b2d9fae75d9..c934020a978f3d2f39c377d312669945cd3c9c28 100644 (file)
@@ -40,15 +40,12 @@ const IMStatus = {
 // Copyright (C) 2008,2009 Red Hat, Inc.
 
 
-function IMStatusItem(label, iconName) {
-    this._init(label, iconName);
-}
-
-IMStatusItem.prototype = {
-    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+const IMStatusItem = new Lang.Class({
+    Name: 'IMStatusItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
     _init: function(label, iconName) {
-        PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
+        this.parent();
 
         this.actor.add_style_class_name('status-chooser-status-item');
 
@@ -61,19 +58,15 @@ IMStatusItem.prototype = {
         this.label = new St.Label({ text: label });
         this.addActor(this.label);
     }
-};
-
-function IMUserNameItem() {
-    this._init();
-}
+});
 
-IMUserNameItem.prototype = {
-    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+const IMUserNameItem = new Lang.Class({
+    Name: 'IMUserNameItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
     _init: function() {
-        PopupMenu.PopupBaseMenuItem.prototype._init.call(this,
-                                                         { reactive: false,
-                                                           style_class: 'status-chooser-user-name' });
+        this.parent({ reactive: false,
+                      style_class: 'status-chooser-user-name' });
 
         this._wrapper = new Shell.GenericContainer();
         this._wrapper.connect('get-preferred-width',
@@ -102,19 +95,15 @@ IMUserNameItem.prototype = {
     _wrapperAllocate: function(actor, box, flags) {
         this.label.allocate(box, flags);
     }
-};
+});
 
-function IMStatusChooserItem() {
-    this._init();
-}
-
-IMStatusChooserItem.prototype = {
-    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+const IMStatusChooserItem = new Lang.Class({
+    Name: 'IMStatusChooserItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
     _init: function() {
-        PopupMenu.PopupBaseMenuItem.prototype._init.call (this,
-                                                          { reactive: false,
-                                                            style_class: 'status-chooser' });
+        this.parent({ reactive: false,
+                      style_class: 'status-chooser' });
 
         this._iconBin = new St.Button({ style_class: 'status-chooser-user-icon' });
         this.addActor(this._iconBin);
@@ -220,7 +209,7 @@ IMStatusChooserItem.prototype = {
             this._userChangedId = 0;
         }
 
-        PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this);
+        this.parent();
     },
 
     // Override getColumnWidths()/setColumnWidths() to make the item
@@ -422,7 +411,7 @@ IMStatusChooserItem.prototype = {
         this._expectedPresence = newPresence;
         this._accountMgr.set_all_requested_presences(newPresence, status, msg);
     }
-};
+});
 
 
 function UserMenuButton() {